package br.ufpi.hu.prescricao.util;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import br.ufpi.hu.prescricao.util.LoadResourceHelper;

/**
 * Geração de relatórios Jasper.
 * 
 * @author Leonardo Sampaio
 * @since 30/01/2013
 *
 */
public class JasperBuilder implements Serializable {

	private static final long serialVersionUID = 3039249805234603482L;
	
	private Map<String, Object> parameters;

	/**
	 * Gera um relatório jasper e retorna o arquivo pdf para o contexto.
	 * 
	 * @param data
	 * @throws IOException
	 * @throws JRException
	 */
	public void gerarRelatorio(Object data) throws IOException, JRException {
		
		String tipoDeRelatorio = "";
		
		ArrayList<Object> dataBeanList = new ArrayList<Object>();
		
		if (data instanceof Collection) {
			if (!((Collection<?>)data).isEmpty()) { //pelo menos 1 elemento
				tipoDeRelatorio = ((Collection<?>)data).iterator().next().getClass().getSimpleName(); //nome da classe
				dataBeanList.addAll((Collection<?>)data);
			}
			else {
				throw new JRException("Erro ao gerar relatório, tente novamente.");
			}
		}
		
		else {
			dataBeanList.add(data);
			tipoDeRelatorio = data.getClass().getSimpleName();
		}

		FacesContext context = FacesContext.getCurrentInstance();

		LoadResourceHelper load = new LoadResourceHelper();

		Hashtable<String, String> env = load.carregarResource("system.conf");

		String reportPath = ((ServletContext) context.getExternalContext().getContext()).getRealPath(env.get(tipoDeRelatorio));

		JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(dataBeanList);
		
		String reportsDirPath = context.getExternalContext().getRealPath("resources/"); //padrão de diretório para logotipos : resources/logo
		
		if (parameters==null)
			parameters = new HashMap<String, Object>();
		parameters.put("reportsDirPath", reportsDirPath); //diretório relativo

		JasperPrint jasperPrint = JasperFillManager.fillReport(reportPath, parameters, beanColDataSource);

		HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
		response.setContentType("application/pdf");
		response.addHeader("Content-disposition", "attachment; filename=\""+tipoDeRelatorio+".pdf\""); //arquivo pdf com nome genérico

		JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
		context.getApplication().getStateManager().saveView(context);
		context.responseComplete();
	}
	
	/**
	 * Gera um relatório jasper com parâmetros adicionais ($P{param})
	 * 
	 * @param data
	 * @param parameters
	 * @throws IOException
	 * @throws JRException
	 */
	public void gerarRelatorio(Object data, Map<String, Object> parameters) throws IOException, JRException {
		
		this.parameters = parameters;
		
		gerarRelatorio(data);
	}

}
